home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Programming / AmigaE / Src / Tools / EasyGUI / Docs / EasyGUI.doc < prev    next >
Encoding:
Text File  |  1997-10-26  |  60.9 KB  |  1,323 lines

  1.                                Introducing:
  2.  
  3.                           E A S Y G U I   v3.3b4
  4.  
  5.         An interface builder for E, with the following highlights:
  6.  
  7.           - It's totally Font-Sensitive
  8.           - It's Resizable
  9.           - It's Self-Organising, i.e. it arranges gadgets
  10.           - It's more StyleGuide compliant than your granny
  11.           - It's Fast and Flexible
  12.           - It's relatively small, needs no extra external libraries
  13.           - The layout-engine is user-extendable with PLUGINs
  14.           - And above all: It's extremely easy to use!!!
  15.  
  16. +---------------------------------------------------------------+
  17. |       0. History                                              |
  18. +---------------------------------------------------------------+
  19.  
  20. As of v3.3a, maintained by Jason R. Hulance, who you can contact at
  21. the addresses given in the Beginner's Guide to Amiga E.
  22. (Email: jason@fsel.com)
  23.  
  24. [v3.3b4:]
  25. - Fixed changegui() window resizing to move window as well, if
  26.   necessary.
  27.  
  28. [v3.3b3 is a minor update that fixes a bug with AppWindow messages
  29. that crept in under the guise of a safety feature in v3.3b...]
  30.  
  31. Changes from the v3.3b version:
  32. - Fixed bug: STR, INTEGER and CHECK gadgets' action functions were not
  33.   getting passed the correct new value parameter.
  34. - Fixed bug: LISTV wasn't always wide enough for label.
  35. - Added EG_HIDE tag to enable the GUI to be created with a hidden (closed)
  36.   window.
  37. - Changed blockwin()/unblockwin() so they now nest properly.
  38.  
  39. Changes from the v3.3a version:
  40. - MAJOR CHANGE: made the main functions use a taglist for their optional
  41.   arguments (it was getting a bit ridiculous...).  This gives a bit more
  42.   flexibility for the programmer and makes for much more readable code, so
  43.   I'm afraid it was inevitable.  To ease the change-over a bit there is an
  44.   example module which gives the old style versions of the functions (just
  45.   for EasyGUI.m; you can do your own for EasyGUI_lite.m).
  46. - MAJOR ADDITION: support for multi-window GUIs.  This is via the
  47.   multiinit(), addmultiA(), multimessage(), cleanmulti() and checkmulti()
  48.   functions.  The new scheme shares message ports, and efficiently
  49.   dispatches on the message data.  This is *massively* more efficient than
  50.   using the old scheme (OR-ing the signal masks of each window), and
  51.   effectively removes the limit of windows that a GUI can use.
  52. - Changed 'info' default to -1, which now gets translated to the guihandle.
  53.   This helps a lot with multi-window GUIs.
  54. - Changed 'data' default to -1, which now gets translated to the gadget
  55.   (not the *real* gadget, but the one that can be used with the setXXX()
  56.   functions). 
  57. - Changed the default screen to be the *default* public screen (rather than
  58.   specifically Workbench).
  59. - Changed AppWindow gadget location code to make it more robust, and now
  60.   includes the gadget label as "hittable".
  61. - Added a short description of the examples to this doc.
  62. - Added a reference to the guihandle to each PLUGIN so they can more easily
  63.   access the GUI window and use the GUI manipulation functions.
  64. - Added closewin()/openwin() to enable the window to be temporarily closed
  65.   and opened.  These are most useful for iconification (see the iconify and
  66.   toolify PLUGINs).  Note that this new feature may break old PLUGINs that
  67.   assume the GUI window will never change.
  68. - Added extra 'maxw' and 'maxh' parameters to make window open with maximum
  69.   width/height (taking into account position, too).
  70. - Added extra 'wintype' parameter to give control over window borders.
  71. - Added some more changeXXX() functions, and changed (sorry!) the other
  72.   changeXXX() functions to make them more uniform.
  73. - Added extra checking in message loop to ignore stray IDCMP_MOUSEMOVE
  74.   messages.  This is needed because GadTools doesn't identify the gadget if
  75.   you use GACT_FOLLOWMOUSE, so your PLUGIN finds it hard to trap this
  76.   message properly.
  77.   [Problem reported by Ralph Wermke <wermke@rz.uni-greifswald.de>]
  78. - Fixed bug in key handling code for the SLIDER gadget.
  79.   [Bug reported first by Fred van der Zee <free@xs4all.nl>]
  80. - Fixed an old bug: guihandles weren't deallocated by cleangui().
  81. - Fixed an old bug: some messages weren't getting replied.
  82. - Fixed an old bug: window wasn't being centred on screen if smaller than
  83.   display (and may not have been openable).
  84. - Minor changes to the layout of a couple of gadgets.
  85. - Made gadtoolsbase and workbenchbase public, mainly so that PLUGINs
  86.   can use them (if you have a GUI open then they must be valid).
  87. - Made things more friendly for multi-tasking: gh.wnd is NIL when the
  88.   GUI is in an unmodifiable state.
  89. - Made awprocs use a copy of the appmessage, mainly so that they can do
  90.   things like manipulate the GUI without problems.
  91. - Made a third version of EasyGUI.  This is EasyGUI_debug.m, which is the
  92.   same as EasyGUI.m except that it will print a short diagnostic message
  93.   before raising an exception.  This should be used when developing your
  94.   program to help track down the actual reason for a fault.
  95.  
  96. Changes from the v3.2e version:
  97. - Lots of minor fixes to most gadgets.
  98. - Added conditional resizing.
  99. - Added (optional) data field for all gadgets.
  100. - Added Style Guide compliant keyboard shortcuts.
  101. - Added extra arguments to some PLUGIN methods.
  102. - Added simple mechanism for PLUGINs to use GadTools gadgets (gtrender()).
  103. - Added AppWindow support for main window, *BUTTON, LISTV, STR and PLUGINs.
  104. - Added a lot of GUI manipulation functions.
  105. - Made an EasyGUI_lite version without a lot of features.
  106.  
  107. changes from the v3.2a version:
  108. - now supports PLUGINs for unlimited complex gui's!!! (check section 5)
  109. - added settext() and setnum()
  110. - fixed NUM gadget
  111. - added topaz-fallback version
  112. - bug: rendered into the border when used with sysihack
  113. - bug: could cause enforcer hits when some strings were NIL
  114. - bug: dealocation of resources in wrong order caused problems
  115.  
  116. changes from the v3.1a version:
  117. - new functions to access/modify gadgets while GUI is active
  118. - easily add gadtools menus
  119. - more complete docs
  120. - works better with multiple simultanuous EasyGUIs
  121. - LISTV, MX and CYCLE have an extra "current" parameter now
  122. - STR now takes an _estring_ as value (change this in old sources!)
  123. - bug: current gadget values would reset upon resize
  124. - bug: would open in middle of screen instead of visible part
  125. - many tiny bugs removed
  126.  
  127. +---------------------------------------------------------------+
  128. |       1. EasyGUI Intro                                        |
  129. +---------------------------------------------------------------+
  130.  
  131. EasyGUI takes the form a module file that needs to be included into your E
  132. source (needless to say, it needs v2.04/v37 of the OS).  The most simple
  133. form of constructing a GUI consist of calling the function easyguiA() with
  134. a (possibly nested) E list which describes your GUI.  just to show how
  135. Easy, try this source:
  136.  
  137.         MODULE 'tools/EasyGUI'
  138.         PROC main() IS easyguiA('um,...',[BUTTON,0,'Ok!'])
  139.  
  140. This'll open a window with just one gadget in it, and wait for the user to
  141. push it. If easyguiA() can't get what it wants, it'll start throwing around
  142. exceptions, so we'll probably need an exception handler to be able to
  143. inform the user properly (see below).
  144.  
  145. The first arg of easyguiA() is the window title, the second one is the GUI
  146. description. The form of these desciptions is quite simple: It's a list
  147. with as first element the type of gadget, the second is called an action
  148. value (more later), and the rest is gadget-specific.
  149.  
  150. To be able to build GUI's outof more components than just one gadget, one
  151. can group gadgets with a ROW and a COL list:
  152.  
  153.         [COLS,
  154.           [BUTTON,1,'Ok'],
  155.           [BUTTON,0,'Cancel']
  156.         ]
  157.  
  158. This'll create a new group, consisting of two gadgets next to each other.
  159. COLS and ROWS groups are like a single gadget, i.e. you can easily put them
  160. into other groups, to create GUI's of infinite complexity.
  161.  
  162. Other Grouping functions are EQCOLS and EQCOLS, which try to align gadgets
  163. in a group. IF you get strange layouts using these, you should try grouping
  164. subgroups before putting them in a larger group.
  165.  
  166. [BEVEL,a] will put a bevel box around a, whatever it is (a gadget, a
  167. group...), and BEVELR is the recessed version.
  168.  
  169. Other elements of groups are mostly gadgets, which have a specific #of
  170. arguments. [If the number of arguments is incorrect, EasyGUI will raise the
  171. "Egui" exception.]
  172.  
  173. The first element is always the type of gadget to create (see below). The
  174. second element is always something called an "actionvalue", which tells
  175. EasyGUI what needs to be done when the user interacts with the gadget.  All
  176. elements after that are gadget specific.
  177.  
  178. An action value may be:
  179. - a small positive integer (0-1000). If the user selects this gadget,
  180.   EasyGUI will close the window, and return that value as returnvalue from
  181.   the easyguiA() call. This is meant for "Ok" / "Cancel" type buttons.
  182. - a pointer to an "action function". If the user selects this gadget,
  183.   EasyGUI will call the function with as arguments depending on the type of
  184.   gadget (for example a slider will get it's current value).  After the
  185.   actionfunction returns, EasyGUI continues processing messages from the
  186.   GUI.
  187.   example:
  188.  
  189.         ...[BUTTON,{load},'Load'],...
  190.  
  191.         PROC load(info) IS WriteF('You pushed the "Load" button!\n')
  192.  
  193.   
  194.   the value of `info' is explained below. Or:
  195.  
  196.         DEF s[100]:STRING
  197.  
  198.         ...[STR,{str},'input:',s,50,4],
  199.            [CYCLE,{cycle},'choose:',['Yep','Nope',NIL],1],...
  200.  
  201.         PROC str(info,news) IS WriteF('the new string is: \s\n',news)
  202.         PROC cycle(info,newc) IS WriteF('the new choice is: \d\n',newc)
  203.  
  204.   In the action function, you can store the new value, however EasyGUI
  205.   keeps track of it itself too: In the case of the STR above it will
  206.   StrCopy() new values into your estring, so it automatically has the
  207.   correct value after closing. In the case of all other gadgets it stores
  208.   the new (integer) value in the list (so that `1' in `CYCLE' may become
  209.   `0').  This has the added benefit that windows that are opened and then
  210.   closed again will automatically start with the current values.
  211.  
  212.   If you want to close the GUI from an action function then you can call
  213.   the quitgui() function, which raises a "QUIT" exception (be careful to
  214.   not handle this exception in your code -- just ReThrow() it if your
  215.   action function has an exception handler).  The single argument to
  216.   quitgui() (which defaults to 0) will be returned from the easyguiA() call,
  217.   in the same way that action values are.  The definition of quitgui() is:
  218.  
  219.         PROC quitgui(ret=0) IS Throw("QUIT",ret)
  220.  
  221.   There are two new, optional arguments to action functions: `qual' and
  222.   `data'.  If you wish to use these arguments your action function must
  223.   include them at the beginning (and you must have a `data' argument if you
  224.   want to use the `qual' argument).  For instance, a button action function
  225.   can be defined in any of these three ways:
  226.  
  227.          PROC action(info) IS WriteF('info=$\h\n',
  228.                                      info)
  229.          PROC action(data,info) IS WriteF('info=$\h,data=$\h\n',
  230.                                           info,data)
  231.          PROC action(qual,data,info) IS WriteF('info=$\h,data=$\h,qual=$\h\n',
  232.                                                info,data,qual)
  233.  
  234.   (This scheme gives *full* compatibility with the old EasyGUI action
  235.   functions, whilst still allowing the new features to be used.)
  236.  
  237.   The `data' argument is the optional data field specified in the gadget.
  238.   If it is not specified or it's -1 then the actual data value that is used
  239.   is the gadget list pointer (for use with the setXXX() functions).  You
  240.   could use it, instead, to pass a pointer to an object specific to the
  241.   gadget.  The action function can then just call a method of that object.
  242.   This allows the same action function to be used by a number of different
  243.   gadgets, with the specific action being carried out via the data element
  244.   (since the data can be different for each gadget).
  245.  
  246.   The `qual' is basically the qualifier part of the intuimessage used to
  247.   indicate gadget clicks.  Use the IEQUALIFIER_XXX constants from the
  248.   module 'devices/inputevent' to see which qualifiers were pressed when
  249.   the gadget was clicked.  For example:
  250.  
  251.         PROC buttonaction(qual,data,info)
  252.           IF qual AND (IEQUALIFIER_LSHIFT OR IEQUALIFIER_RSHIFT)
  253.             PrintF('You were pressing a shift key when you clicked on me!\n')
  254.           ENDIF
  255.         ENDPROC
  256.  
  257. The easyguiA() function:
  258.  
  259.         easyguiA(windowtitle,gui,tags=NIL)
  260.  
  261. `tags' is a taglist which can use the following tags:
  262.  
  263. EG_INFO
  264.   the data may be ANY value, and is passed as an arg to the action
  265.   functions.  For example if you write a prefsrequester, this may be the
  266.   the prefs OBJECT.  Your actionfunctions then have a simple task changing
  267.   the value of the element in question.  (If this is -1 or not present,
  268.   then it the info used will be the 'guihandle' value for this GUI.  See
  269.   Chapter 4.)
  270.  
  271. EG_SCRN
  272.   the data is an optional screen ptr to open on. if NIL or not present
  273.   EasyGUI opens on the default public screen (usually Workbench).
  274.  
  275. EG_FONT
  276.   the data is a fontdescription (i.e., a `textattr').  If NIL or not
  277.   present, EasyGUI will use the same font as the screen (for Workbench this
  278.   is the font the user selected as "screenfont" in fontprefs).
  279.  
  280. EG_MENU
  281.   the data is a newmenus structure (as in gadtools.library). EasyGUI will
  282.   then automatically attach it to the window and arrange any messages.  You
  283.   can give the same actionvalues as gadgets in the newmenu.userdata, and
  284.   the actionfunction can be the same as for a `BUTTON', i.e.:
  285.  
  286.         [...,NM_ITEM,0,'Load','l',0,0,{load},...]:newmenu
  287.  
  288.   can use the same load() as in the example further above (the optional
  289.   `qual' and `data' arguments [see below] will always be NIL). [The
  290.   constants NM_ITEM, etc., are from the module 'libraries/gadtools'.]
  291.  
  292. EG_GHVAR
  293.   the data is the address of a LONG variable which gets a copy of the
  294.   guihandle (see Multiple Windows, below).  You just specify something like
  295.   {gh} instead of having to use guiinitA(), etc.  Note that you can also
  296.   get the guihandle by using the new default for the `info' of a GUI
  297.   (as described above).
  298.  
  299. EG_AWPROC
  300.   the data is a function to be called when the user drops icons on the
  301.   window (and no gadget handles the drop).  By default, this is NIL and
  302.   this means that the window will not to be made into an AppWindow.  If
  303.   it's *not* NIL then the window *will* be an AppWindow, and the *BUTTON,
  304.   LISTV and STR gadgets will get their awprocs called if icons are dropped
  305.   directly on them (PLUGIN gadgets can also react to AppWindow messages).
  306.   If the drop does not land on a gadget with an awproc then this awproc
  307.   (for the whole window) will be called.  (See the examples.)  awprocs are
  308.   like action functions and can be defined in one of two ways:
  309.  
  310.         PROC awproc(info,awmsg:PTR TO appmessage)
  311.         PROC awproc(data,info,awmsg:PTR TO appmessage)
  312.  
  313.   `info' is the GUI info, `awmsg' is a *copy* of the appmessage and `data'
  314.   is the optional data field for the gadget (or the `plugin_object' for
  315.   PLUGINs, and NIL for the window one).
  316.  
  317. EG_TOP, EG_LEFT
  318.   the data define the top-left coordinate of the window.  If either of them
  319.   is -1 (the default), then the window will be centred on that axis (in the
  320.   visible part of the screen).
  321.  
  322. EG_MAXW, EG_MAXH
  323.   the (boolean) data specify whether to try make the window size maximal in
  324.   width or height (based on screen size), rather than the default of
  325.   minimal (based on the GUI).  If you specify a position then the maximal
  326.   size of that axis will be the remaining part of the screen.  So, on a
  327.   screen of width 640, if you specify EG_LEFT of 100 then the maximum width
  328.   the window can be is 540.
  329.  
  330. EG_WTYPE
  331.   the data is a constant to dictate the window decoration (i.e., what
  332.   happens with the borders).  The choices are:
  333.  
  334.         WTYPE_SIZE     the default, which gives you all the standard
  335.                        gadgets and a size gadget at the bottom.
  336.         WTYPE_NOSIZE   omits the size gadget.
  337.         WTYPE_BASIC    just has a simple border around the window.
  338.         WTYPE_NOBORDER has (suprisingly) no border.
  339.  
  340.   Be careful with these last two options as there is no close gadget for
  341.   the user to click -- you must provide them with your own method of
  342.   closing the GUI (a menu item?).  (Note: the window title is ignored with
  343.   the last two types, since there's no title bar.)
  344.  
  345. EG_CLOSE
  346.   the data is an action value/function used when the user clicks the close
  347.   gadget on the GUI window.  This is most useful for multi-window GUIs (see
  348.   Multiple Windows), but it can be useful to prompt the user to confirm
  349.   before quitting the GUI.  The action value will be returned from
  350.   easyguiA()/guimessage()/multiloop()/multimessage(), as usual.  The action
  351.   function can be defined in one of two ways:
  352.  
  353.         PROC closeproc(info)
  354.         PROC closeproc(mh:PTR TO multihandle,info)
  355.  
  356.   `info' is the GUI's info parameter (see above), and `mh' is the
  357.   multi-window handle (see Multiple Windows) or NIL if it's a single window
  358.   GUI.
  359.  
  360. EG_CLEAN
  361.   the data is a function to be called when the GUI is destroyed (e.g., by
  362.   calling cleangui()).  This is most useful for multi-window GUIs (see
  363.   Multiple Windows), but it can generally be useful for cleaning up the
  364.   GUI's PLUGINs (see Chapter 5).  The function will be called *after* the
  365.   window and the GUI has been closed and deallocated, so, for example, the
  366.   PLUGINs will no longer be on screen.  It should be defined like this:
  367.  
  368.         PROC cleanproc(info)
  369.  
  370.   `info' is the GUI's info parameter (see above).  Note: if guiinitA() or
  371.   addmultiA() cause an exception then this function will *not* be called.
  372.   This makes it easier to setup a GUI (see the examples).
  373.  
  374. EG_HIDE
  375.   the (boolean) data specifies whether the GUI window is initially hidden
  376.   (closed).  The default is FALSE; if you specify TRUE then you can use
  377.   openwin() to show the window when you want it to be seen.  Note: this tag
  378.   is a bit useless for a normal call to easyguiA() as there's little chance
  379.   of it receiving any GUI messages if the window is closed (so the Wait()
  380.   will never return).
  381.  
  382.  
  383. +---------------------------------------------------------------+
  384. |       2. Gadgets                                              |
  385. +---------------------------------------------------------------+
  386.  
  387. general format: [NAME,action,text,...]
  388. in {}: which direction it may resize.
  389. + = a value that can be affected lateron with the set#? functions
  390. * = optional value (can be omitted)
  391.  
  392. Each gadget shows the gadget template, explanation, the form of the
  393. actionfunction, and a typical example.
  394.  
  395. The optional arguments to action functions (qual and data) are described in
  396. the above chapter.
  397.  
  398.  
  399. [BUTTON,action,intext,data*,key*,awproc*,disabled+*]
  400.   data = user data value passed to action function
  401.   key = keyboard shortcut (presses button)
  402.   awproc(data*,info,awmsg) = AppWindow proc (see above)
  403.   disabled = whether this gadget is disabled or not
  404.   buttonaction(qual*,data*,info)
  405.   example: [BUTTON,0,'Cancel']
  406.  
  407. [CHECK,action,righttext,checkedbool+,lefttextbool,data*,key*,disabled+*]
  408.   checkedbool = whether gadget should initially be check-marked
  409.   key = keyboard shortcut (toggles check)
  410.   disabled = whether this gadget is disabled or not
  411.   checkaction(qual*,data*,info,checkedbool)
  412.   example: [CHECK,{case},'Ignore case',TRUE,FALSE]
  413.  
  414. [INTEGER,action,lefttext,num+,relsize,data*,key*,disabled+*]
  415.   num = initial value
  416.   key = keyboard shortcut (activates gadget)
  417.   disabled = whether this gadget is disabled or not
  418.   integeraction(qual*,data*,info,newnum) {x}
  419.   example: [INTEGER,{v},'int:',5,3]
  420.   (Note: see discussion of getinteger() in chapter 4 below.)
  421.  
  422. [LISTV,action,textabove,relx,rely,execlist+,readbool,selected,current+,
  423.        data*,key*,awproc*,disabled+*]
  424.   execlist = ptr to an execlist. (see tools/constructors.m)
  425.   readbool = whether listview is read-only (action is ignored if it is!)
  426.   selected = 0=none, 1=highlight/show selected
  427.   key = keyboard shortcut (unshifted->select next, shifted->prev)
  428.   awproc(data*,info,awmsg) = AppWindow proc (see above)
  429.   disabled = whether this gadget is disabled or not
  430.   listviewaction(qual*,data*,info,num_selected) {x,y}
  431.   example: [LISTV,0,NIL,5,5,filenamelist,0,NIL,0]
  432.   (Note: disabling doesn't work under V37.)
  433.  
  434. [MX,action,righttext,nil_term_elist,lefttextbool,current,
  435.     data*,key*,disabled+*]
  436.   (Note: under v37 the righttext is spaced correctly but not rendered.)
  437.   key = keyboard shortcut (unshifted->next choice, shifted->prev, wraps)
  438.   disabled = whether this gadget is disabled or not
  439.   mxaction(qual*,data*,info,num_selected)
  440.   example: [MX,{v},NIL,['One','Two','Three',NIL],FALSE,1]
  441.   (Note: disabling doesn't work under V37.)
  442.  
  443. [CYCLE,action,lefttext,nil_term_elist,current,data*,key*,disabled+*]
  444.   key = keyboard shortcut (unshifted->next choice, shifted->prev, wraps)
  445.   disabled = whether this gadget is disabled or not
  446.   cycleaction(qual*,data*,info,num_selected)
  447.   example: [CYCLE,{v},'choose:',['Yep','Nope',NIL],1]
  448.  
  449. [PALETTE,action,lefttext,depth,relx,rely,current+,data*,key*,disabled+*]
  450.   (Note: the current field is new to v3.3a and is _not_ optional, so any
  451.   existing v3.2e sources using a PALETTE gadget will need a small edit.)
  452.   depth = 1..8, number of bitplanes this color is for
  453.   key = keyboard shortcut (unshifted->next pen, shifted->prev, wraps)
  454.   disabled = whether this gadget is disabled or not
  455.   paletteaction(qual*,data*,info,colour) {x,y}
  456.   example: [PALETTE,{v},'color:',3,5,2]
  457.  
  458. [SCROLL,action,isvert,total+,top+,visible+,relsize,data*,key*,disabled+*]
  459.   total = resolution of scroller
  460.   top = current top represented
  461.   visible = current
  462.   key = keyboard shortcut (unshifted->increment, shifted->decrement)
  463.   disabled = whether this gadget is disabled or not
  464.   scolleraction(qual*,data*,info,curtop) {x|y}
  465.   example: [SCROLL,{v},FALSE,10,0,2,2]
  466.  
  467. [SLIDE,action,lefttext,isvert,min,max,cur+,relsize,levelformat,
  468.        data*,key*,disabled+*]
  469.   min,max = value range of slider
  470.   cur = current value
  471.   levelformat = string that shows levelformat, example '%2ld'. leave
  472.     a large amount of spaces left in lefttext for this.
  473.   key = keyboard shortcut (unshifted->increment, shifted->decrement)
  474.   disabled = whether this gadget is disabled or not
  475.   slideraction(qual*,data*,info,cur) {x|y}
  476.   example: [SLIDE,0,'Colors:',FALSE,1,8,3,5,'']
  477.  
  478. [STR,action,lefttext,initial+,maxchars,relsize,
  479.      over*,data*,key*,awproc*,disabled+*]
  480.   initial = initial string contents: NOTE: HAS TO BE AN ESTRING!
  481.   maxchars = max #of chars for string
  482.   over = overwrite mode boolean (default is FALSE, i.e., insert mode)
  483.   key = keyboard shortcut (activates gadget)
  484.   awproc(data*,info,awmsg) = AppWindow proc (see above)
  485.   disabled = whether this gadget is disabled or not
  486.   stringaction(qual*,data*,info,string) {x}
  487.   (Note: action function is passed the E-string, not the gadget's buffer.)
  488.   example: [STR,0,'Pattern',s,100,5]      (DEF s[100]:STRING)
  489.   (Note: see discussion of getstr() in chapter 4 below.)
  490.  
  491. [TEXT,text,lefttext,borderbool,relsize] {x}
  492.   borderbool = whether or not a recessed bevelbox is placed around 'text'
  493.   example: [TEXT,'Selected Fonts',NIL,FALSE,3]
  494.  
  495. [NUM,int,lefttext,borderbool,relsize] {x}
  496.   borderbool: as TEXT
  497.   example: [NUM,123,'num:',TRUE,5]
  498.  
  499. [SBUTTON,action,intext,data*,key*,awproc*,disabled+*] {x}
  500.   same as button, only now resizes horizontally.
  501.  
  502. [PLUGIN,action,plugin_object,isgt*,awproc*]
  503.   isgt = whether this PLUGIN is made from GadTools gadgets (see chapter 5)
  504.   awproc(plugin_object*,info,awmsg) = AppWindow proc (see above)
  505.   pluginaction(info,plugin_object)
  506.   (see separate chapter 5 on using/implementing these).
  507.  
  508. [BAR], [SPACE] {x,y}, [SPACEH] {x}, [SPACEV] {y}
  509.   BAR places a nice divider-bar between gadgets/groups. Whether it's
  510.   horizontal or vertical depends on which group it is in.
  511.   SPACE/SPACEH/SPACEV do nothing, they only eat up space. This can be very
  512.   handy in GUI design, they act like a spring between elements (do not use
  513.   them on the borders of a GUI, only in the middle).
  514.  
  515.  
  516. #?text:
  517.   (where #? is left/right etc.): a text to place next to the gadget.  Often
  518.   is allowed to be NIL.
  519.  
  520. relsize,relx,rely:
  521.   Generally gadgets will automatically get a size depending on a number of
  522.   factors, but relsize allows the programmer to give a minimum size for
  523.   certain gadgets, thereby sizing a whole group.  If other gadgets already
  524.   account for the minimum size, this one can safely be set to a low value
  525.   such as 2.  All these sizes are calculated in terms of the _height_ of
  526.   the font.  Always try out your GUI with different fonts.  For example if
  527.   you design a gui that only just fits horizontally with an 8 point font on
  528.   640x200, when run on with a 13 point font on 640x512, the gui will be
  529.   quite a bit bigger horizontally, but the screen isn't, so it won't fit.
  530.   (see also: the "bigg" exception below).
  531.  
  532. nil_term_elist:
  533.   a nil-terminated E list, such as ['One','Two','Three',NIL]
  534.  
  535. isvert:
  536.   TRUE if gadget needs to be vertical, horizontal by default.
  537.  
  538. key:
  539.   All keyboard shortcuts are optional (so marked with a * in the following
  540.   descriptions).  If specified then they must be lowercase letters ("a" to
  541.   "z").  However, the shifted and unshifted keystrokes are *both* handled,
  542.   in the way described by the Style Guide (and this is briefly outlined for
  543.   each gadget).  Also, if a key is specified then an "_" in the gadget
  544.   label text indicates the character in the label which is to be
  545.   underscored (and this ought to be the same letter as the key).  If a key
  546.   is not specified then any "_"s in the label are not special.  (If an
  547.   action function is invoked as a result of a key press then the `qual'
  548.   will always be 0.)
  549.  
  550. disabled:
  551.   If this optional field is specified then the gadget can be disabled and
  552.   enabled using the setdisabled() function (see below, chapter 4), and the
  553.   current status of the gadget will be recorded in this field, too.
  554.  
  555.  
  556. The following constants/enumerations are defined in order to make
  557. referencing/creating the lists for each gadget a bit more readable.
  558.  
  559.   EXPORT ENUM BEV_GUI=1,
  560.     BUT_ACT=1, BUT_TXT,  BUT_DATA, BUT_KEY,  BUT_APPW, BUT_DIS,
  561.     CHK_ACT=1, CHK_TXT,  CHK_VAL,  CHK_LEFT, CHK_DATA, CHK_KEY,  CHK_DIS,
  562.     INT_ACT=1, INT_TXT,  INT_VAL,  INT_REL,  INT_DATA, INT_KEY,  INT_DIS,
  563.     LST_ACT=1, LST_TXT,  LST_RELX, LST_RELY, LST_LIST, LST_RO,   LST_SHOW,
  564.                LST_CURR, LST_DATA, LST_KEY,  LST_APPW, LST_DIS,
  565.      MX_ACT=1,  MX_TXT,   MX_LIST,  MX_LEFT,  MX_CURR,  MX_DATA,  MX_KEY,
  566.                 MX_DIS,
  567.     CYC_ACT=1, CYC_TXT,  CYC_LIST, CYC_CURR, CYC_DATA, CYC_KEY,  CYC_DIS,
  568.     PAL_ACT=1, PAL_TXT,  PAL_DEP,  PAL_RELX, PAL_RELY, PAL_CURR, PAL_DATA,
  569.                PAL_KEY,  PAL_DIS,
  570.     SCR_ACT=1, SCR_VERT, SCR_TOTL, SCR_TOP,  SCR_VIS,  SCR_REL,  SCR_DATA,
  571.                SCR_KEY,  SCR_DIS,
  572.     SLI_ACT=1, SLI_TXT,  SLI_VERT, SLI_MIN,  SLI_MAX,  SLI_CURR, SLI_REL,
  573.                SLI_FMT,  SLI_DATA, SLI_KEY,  SLI_DIS,
  574.     STR_ACT=1, STR_TXT,  STR_STR,  STR_MAX,  STR_REL,  STR_OVR,  STR_DATA,
  575.                STR_KEY,  STR_APPW, STR_DIS,
  576.     TXT_VAL=1, TXT_TXT,  TXT_BORD, TXT_REL,
  577.     NUM_VAL=1, NUM_TXT,  NUM_BORD, NUM_REL,
  578.     PLG_ACT=1, PLG_OBJ,  PLG_GT,   PLG_APPW
  579.  
  580.  
  581. +---------------------------------------------------------------+
  582. |       3. How Layout Works                                     |
  583. +---------------------------------------------------------------+
  584.  
  585. EasyGUI works by automatically layouting the gadgets on the screen. In a
  586. first pass, it will compute the minimum size for each element: for gadgets
  587. this involves the size of fonts and various other things. For a ROWS list,
  588. for example, it will take the width of the biggest gadget as its width, and
  589. computes its height by adding the heights of all other gadgets. For EQROWS
  590. this is slightly more complicated: EasyGUI also computes a "middle" for
  591. various gadgets, often between the text that denotes what a gadget is about
  592. and the gadget itself. It then tries to align all of these. for EQCOLS it
  593. simply tries to make all columns equal width.
  594.  
  595. In a second pass, EasyGUI assigns the final coordinates to all gadgets.
  596. Important to notice is that in a GUI often there is more space available
  597. than is required for a gadget, for example the gadget above it in a ROWS
  598. environment is much wider. Also, the user may have resized the window. To
  599. do something useful with this space, EasyGUI looks at which gadgets can do
  600. something useful with extra space, such as LISTV, or STR, SCROLL etc. This
  601. process of granting extra space propagates through ROWS/COLS, which act as
  602. gadgets themselves. Gadgets like BUTTON don't benefit from more space, so
  603. they give that away to their neighbours.
  604.  
  605.  
  606. +---------------------------------------------------------------+
  607. |       4. Advanced features                                    |
  608. +---------------------------------------------------------------+
  609.  
  610. Different versions of EasyGUI
  611. -----------------------------
  612. For those who care more about saving a few KB than the extra functionality,
  613. there are two different versions:
  614.  
  615.      1) EasyGUI_lite.m
  616.         This does not have multi-window support, keyboard support for
  617.         gadgets, AppWindow support or GUI manipulation functions (i.e.,
  618.         dynamically changing a GUI, window blocking and gadget disabling).
  619.           Current code size: 17324 bytes.
  620.      2) EasyGUI.m
  621.         The full version, with nothing taken out.
  622.           Current code size: 23968 bytes.
  623.  
  624. There's also a third version of EasyGUI which is just a variant of
  625. EasyGUI.m: this is a debug version, EasyGUI_debug.m, which gives some more
  626. information about an error before raising an exception (so you shouldn't
  627. really distribute programs compiled with this module -- it's just for
  628. development purposes).
  629.  
  630.  
  631. Throwing exceptions from actionfunctions
  632. ----------------------------------------
  633. is allowed: EasyGUI will catch it, close the window properly, and then
  634. ReThrow() if it wasn't a "QUIT" exception.  If it was "QUIT" then the
  635. exceptioninfo value will be the return value of the easyguiA()/guimessage()
  636. or multiloop()/multimessage() functions, just like the way actionvalues
  637. work (except for the slight difference in a multi-window GUI, as noted
  638. below).
  639.  
  640. Exceptions raised by EasyGUI itself:
  641.  
  642. "MEM"   -- no mem
  643. "GUI"   -- for things like CreateGadgetA, OpenWindowTagList etc.
  644. "GT"    -- couldn't open gadtools.library
  645.  
  646. "bigg"  -- for "BIG Gui": interface is calculated to be bigger than the
  647.            screen.  Generally you should keep gui's small, so that they
  648.            still fit on 640x200 topaz screens. If the user runs Times/30 on
  649.            a screen this size, he probably knows he has a problem.
  650. "Egui"  -- a design error: most probably handed over a list to dogui() that
  651.            was either to long or too short
  652. <other> -- Raise()ed by own function
  653.  
  654.  
  655. Multiple Windows
  656. ----------------
  657. There are two ways of handling multiple windows in EasyGUI.  The first
  658. has really been superseded by the second, though.
  659.  
  660. 1) The simplest use of EasyGUI is just by calling easyguiA(). You can
  661.   however open any number of windows, and check messages for all of them.
  662.  
  663.         guiinitA(windowtitle,gui,tags=NIL)
  664.         guimessage(guihandle)
  665.         cleangui(guihandle)
  666.  
  667.   Call guiinitA() for each window (exactly the same arguments as
  668.   easyguiA().  Then, keep calling guimessage() for each of them, when
  669.   messages arive.  you can close them again with cleangui(), for example
  670.   when a gui returns a positive integer (the actioncode). Negative integers
  671.   signal that it simply finished processing all messages, but no need to
  672.   close the window yet.  Note: it is *not* safe to call cleangui() from
  673.   *any* action function (except as noted below, in the description of
  674.   cleanmulti()).  (If you want to close the GUI prematurely, you can use
  675.   the closewin() function.)
  676.  
  677.   example of usage of these three function (= definition easyguiA())
  678.  
  679.         EXPORT PROC easyguiA(windowtitle,gui,tags=NIL) HANDLE
  680.           DEF gh=NIL:PTR TO guihandle,res=-1
  681.           gh:=guiinitA(windowtitle,gui,tags)
  682.           WHILE res<0
  683.             Wait(gh.sig)
  684.             res:=guimessage(gh)
  685.           ENDWHILE
  686.         EXCEPT DO
  687.           cleangui(gh)
  688.           ReThrow()
  689.         ENDPROC res
  690.  
  691.   the object you get has some handy fields in there: the window in question
  692.   `wnd' (or NIL if it's currently closed), the sigmask `sig' (i.e., _not_
  693.   the signal bits) if you want to do a proper Wait() (OR them), the GUI's
  694.   info and the handle for the multi-window group `mh' (or NIL if this is a
  695.   single GUI) [see below for more details on this].
  696.  
  697.         OBJECT guihandle
  698.         /* Public (read-only) parts: */
  699.           wnd:PTR TO window
  700.           sig:LONG
  701.           info
  702.           mh:PTR TO multihandle  -> See below...
  703.         ENDOBJECT
  704.  
  705.   The GUI's info is provided to make retrieving the info from the guihandle
  706.   easier (in an EG_CLEAN proc, for instance).  If you want to draw into
  707.   `wnd': stdrast is automatically set to the last EasyGUI opened.  `wnd'
  708.   can also be used a flag to indicate when it is safe to manipulate the
  709.   GUI (to help with multi-tasking): when it's NIL it's not safe to modify
  710.   the GUI directly, unless you've been passed the window pointer (e.g.,
  711.   render() and clear_render()).  The setXXX() functions are always safe.
  712.   Note: `wnd' can change due to closewin()/openwin() calls which mean that
  713.   the GUI may be in different windows during its life.
  714.  
  715. 2) But starting in v3.3b, there's a much more efficient (and simpler) way
  716.   of handling multiple-window GUIs.  This uses the functions multiinit(),
  717.   addmultiA(), multiloop() (which uses multimessage()) and cleanmulti(), in
  718.   roughly the same way as the single window versions.  It's all based
  719.   around a `multihandle':
  720.  
  721.         OBJECT multihandle
  722.         /* Public (read-only) parts: */
  723.           sig:LONG
  724.           opencount:LONG
  725.         ENDOBJECT
  726.  
  727.         multiinit()
  728.         addmultiA(multihandle,windowtitle,gui,tags=NIL)
  729.         multiloop(multihandle)
  730.         multimessage(multihandle)
  731.         cleanmulti(multihandle)
  732.  
  733.   multiinit() is used to initialise a new group of GUIs and produce a new
  734.   `multihandle'.  It takes no arguments.  You must call this function first
  735.   and use the multihandle with the other functions to refer to your group
  736.   of GUIs.  You can still refer to each individual GUI using a guihandle
  737.   (see below).  A quick example to show how simple the new multi-window
  738.   scheme is:
  739.  
  740.         PROC multiplewindows() HANDLE
  741.           DEF mh=NIL, gh1:PTR TO guihandle, gh2:PTR TO guihandle,res
  742.           mh:=multiinit()
  743.           gh1:=addmultiA(mh,'GUI One',[BUTTON,{but1},'Press Me'])
  744.           gh2:=addmultiA(mh,'GUI Two',[BUTTON,{but2},'Press Me'])
  745.           -> Could add more GUIs...
  746.           res:=multiloop(mh)
  747.         EXCEPT DO
  748.           cleanmulti(mh)
  749.         ENDPROC
  750.  
  751.   addmultiA() is very much like guiinitA().  It creates a new window with
  752.   your specified GUI and returns the guihandle.  You can call this function
  753.   even from action functions, when the GUI group is active.
  754.  
  755.         addmultiA(mh:PTR TO multihandle,windowtitle,gui,tags=NIL)
  756.  
  757.   The extra parameter is `mh' to indicate the group to which this window
  758.   will be added.
  759.  
  760.   If the tag EG_CLOSE is not specified or the data is an action value
  761.   (between 0 and 1000) then the GUI will be destroyed and removed from the
  762.   group (the guihandle will now be invalid) and the action value will be
  763.   returned (from multimessage()) -- just like a normal action value.  If it
  764.   is an action function then the window is *not* closed and the action
  765.   function is called.  As stated above, you define such an action function
  766.   in one of two ways:
  767.  
  768.         PROC closeproc(info)
  769.         PROC closeproc(mh:PTR TO multihandle,info)
  770.  
  771.   `info' is the GUI's info parameter and `mh' is the multihandle for this
  772.   group.  Use `mh' to find the `opencount' -- the number of GUIs with open
  773.   windows.  This count will include this GUI so if it's equal to one then
  774.   you know this is the last open window in the group.  Your action function
  775.   may want to prompt the user and then close the window (using closewin()),
  776.   destroy the GUI and remove it from the group (using cleangui()), or leave
  777.   the window open.
  778.  
  779.   multiloop() is defined in terms of multimessage() and opencount, and is
  780.   similar to the definition of easyguiA().
  781.  
  782.         EXPORT PROC multiloop(mh:PTR TO multihandle)
  783.           DEF res=-1
  784.           WHILE res<0
  785.           EXIT mh.opencount=0
  786.             Wait(mh.sig)
  787.             res:=multimessage(mh)
  788.           ENDWHILE
  789.         ENDPROC res
  790.  
  791.   The signal mask for waiting for messages is `sig' in the multihandle.
  792.   You can use this for more complex Wait()s, and then call multimessage()
  793.   to handle any messages that may have arrived for any of the GUIs.  Any
  794.   action values generated by a GUI (or via quitgui()) are returned by
  795.   multimessage() and hence terminate multiloop().  The above example calls
  796.   multiloop() only once, so an action value will eventually destroy the
  797.   whole group (by calling cleanmulti()).  Note: a real action value will
  798.   cause the GUI that produced it to be closed via cleangui(), but a value
  799.   returned through use of quitgui() will not -- this is because if you've
  800.   called quitgui() then you can just as easily write code to close the
  801.   window (or whatever) in the same action function.
  802.  
  803.   By using the `opencount', the loop will be terminated when there are no
  804.   more open GUI windows.  Alternatively, if you are using your own Wait()
  805.   you might want to check that there are no GUIs left (even ones with
  806.   closed windows).  To this end there's the function multiempty() which
  807.   returns TRUE if and only if there are no GUIs in the group.  (Note: if
  808.   there are only GUIs left with no window then the simple Wait() will never
  809.   return!)
  810.  
  811.   cleanmulti() destroys all GUIs in the group (whether they have an open or
  812.   closed window) and deallocates the multihandle.  It is *not* safe to use
  813.   the multihandle or any of the guihandles after this.  So, in particular,
  814.   it is *not* safe to call cleanmulti() from *any* action function.  It is,
  815.   however, safe to call cleangui() on GUIs in the group, if you are using
  816.   cleanmulti() to do the final cleanup (rather than calling cleangui() on
  817.   remembered guihandles).
  818.  
  819.   To help with manipulating a group there are the multiexists() and
  820.   multiforall() functions, which work in a very similar way to ForAll() and
  821.   Exists().
  822.  
  823.         multiforall(varaddr,mh:PTR TO multihandle,expr)
  824.         multiexists(varaddr,mh:PTR TO multihandle,expr)
  825.  
  826.   `varaddr' is the address of a (global) guihandle variable, `mh'
  827.   identifies the GUI group and `expr' is a quoted expression to be
  828.   evaluated.  multiforall() will evaluate the expression for every GUI in
  829.   the group (whether its window is open or closed) and return TRUE if the
  830.   expression is TRUE (non-zero) for all GUIs, else it will return FALSE.
  831.   multiexists() will stop at the first GUI for which the expression is
  832.   TRUE, and return the value of the expression.  Unlike Exists(), you are
  833.   guaranteed that the variable pointed to by `varaddr' will contain the
  834.   guihandle of the corresponding GUI (or NIL if none were found).  So, you
  835.   can use multiexists() to find GUIs.  Note: be careful what the expression
  836.   does with the guihandle and the GUI group; it is quite safe to cleangui()
  837.   on the supplied guihandle, but it is not safe to affect any other GUI in
  838.   this way.  Any GUIs added to the group by the expression will not be part
  839.   of the forall or exists (for those who can't live without knowing: the
  840.   list is explored from head to tail, and new GUIs are added to the head;
  841.   so the last GUI considered will be the oldest GUI).
  842.  
  843.   For example, you can print the title of each GUI with an open window:
  844.  
  845.         multiforall({gh},mh,`IF gh.wnd THEN WriteF('\s\n',gh.wnd.title) ELSE 0)
  846.  
  847.   A final reminder: `varaddr' must be the *address* of a *global* variable
  848.   (and so must all the variables used in the quoted expression).
  849.  
  850.   Useful note: as long as a guihandle is valid (i.e., as long as cleangui()
  851.   has not been called on it), the normal GUI functions checkgui() and
  852.   guimessage() will actually work on the whole group that a GUI is in.
  853.   (Note: the proper, safe functions to use for multi-window GUIs are
  854.   checkmulti() and multimessage(), respectively.)
  855.  
  856.  
  857. Multiple copies of a GUI
  858. ------------------------
  859. If your app allows to have multiple copies of the _same_ gui open at the
  860. same time (for example if you open windows recursively, or you use the
  861. multiple window technique described above to open more instances of one
  862. GUI), you might need to dynamically allocate the GUI description, because
  863. of the way dynamically computed values are put into static E lists. A GUI
  864. desciption with [] lists is static, i.e. only allocated once. Adding NEW to
  865. all of them is hard to deallocate, and this is where disposegui() comes in.
  866. To safely use this feature, allocate ALL lists belonging to the GUI
  867. desciption dynamically with NEW [...] (this does not include lists such as
  868. the one used for the various labels in CYCLE-gadgets).
  869.  
  870.         easyguiA('Bla',
  871.           gui:=NEW [ROWS,
  872.                  NEW [STR,{str},'input:',s,50,4],
  873.                  NEW [CYCLE,{cycle},'choose:',['Yep','Nope',NIL],1]])
  874.         disposegui(gui)
  875.  
  876. Call disposegui() with the top-level list. On each gadget-list (i.e.,
  877. NEW [CYCLE,...]) it will simply call FastDisposeList(), on COLS and ROWS
  878. etc.  it will first deallocate each element recursively.
  879.  
  880.  
  881. Manipulating Gadgets
  882. --------------------
  883. [This assumes you've got the guihandle by using the ghaddr argument of
  884. easyguiA(), the DIY version of EasyGUI (as described under 'Multiple
  885. Windows'), or you're using the new default for the 'info' of a GUI.]
  886.  
  887. You might need to modify gadgets while a GUI is active, for example to set
  888. a slider when a corresponding integer gadget is modified by the user, or to
  889. change the contents of a listview.
  890.  
  891. You can denote gadgets to change by simply storing their addresses, i.e.:
  892.  
  893.         [COLS,
  894.           mygad:=[CHECK,....],
  895.           ...
  896.         ]
  897.  
  898. Now you can use `mygad' with some of the functions below. Note that, of
  899. course `mygad' isn't a gadget, but it helps EasyGUI to find the real
  900. gadget.
  901.  
  902.         setcheck(gh,gad,bool)
  903.         setinteger(gh,gad,new)
  904.         setlistvlabels(gh,gad,labs)
  905.         setlistvselected(gh,gad,active)
  906.         setlistvvisible(gh,gad,vis)
  907.         setmx(gh,gad,active)
  908.         setcycle(gh,gad,active)
  909.         setpalette(gh,gad,colour)
  910.         setscrolltop(gh,gad,top)
  911.         setscrolltotal(gh,gad,total)
  912.         setscrollvisible(gh,gad,visible)
  913.         setslide(gh,gad,new)
  914.         setstr(gh,gad,new)
  915.         settext(gh,gad,newtext)
  916.         setnum(gh,gad,newnum)
  917.  
  918. for all these: `gh' is the gui you're talking about (as returned from
  919. guiinitA()/addmultiA(), or via the `ghaddr' argument of easyguiA() or the
  920. new default for the 'info' of a GUI), `gad' is a value that denotes the
  921. gadget as described above.  the third value is whatever you're changing
  922. about the gadget. Note that in doing so, you need to respect usual
  923. restrictions on gadtools gadgets, for example setlistvlabels() requires
  924. that you first set it to -1, then modify the list, and put it back.
  925. setlistvvisible() will try to make the indicated item in the LISTV visible.
  926. setlistvselected() will make a new selection and try to make it visible
  927. (and -1 turns off the selection).
  928.  
  929.         setdisabled(gh,gad,disabled=TRUE)
  930.  
  931. This applies to all gadgets, but works only if you've actually specified a
  932. value (TRUE or FALSE) for the optional `disabled' field for the gadget.
  933.  
  934.         realgadget:=findgadget(gh,list)
  935.  
  936. allows you to find the gadget address, for all those modifications that
  937. aren't possible with the above set#? functions. It returns an intuition
  938. gadget structure. Note that preferably you will want to use the set#?
  939. functions, as these cooperate with EasyGUI very well (in keeping track of
  940. the current value, for example: setstr() also copies the new value to the
  941. estring you attached to the gadget).  While there is at least one GUI still
  942. allocated the `gadtoolsbase' and `workbenchbase' are valid, so you can
  943. quite easily manipulate gadgets in action functions using GadTools
  944. functions.  (If you do open either of these libraries, be careful not to
  945. overwrite these variables with NIL!  That is, use an automatic exception on
  946. OpenLibrary() or otherwise check the return value before assigning it.)
  947.  
  948.         getstr(gh,gad)
  949.         getinteger(gh,gad)
  950.  
  951. These return and store the current value of a STR or INTEGER gadget (where
  952. gh and gad are as described above for the setxxx() functions).  They are
  953. useful because Intuition only sends a message (and so causes the current
  954. values to be stored) when the user hits the return or tab key in these
  955. gadgets.  So, if you really want to know a STR or INTEGER gadget's current
  956. value use getstr() or getinteger().
  957.  
  958.  
  959. Topaz Fallback
  960. --------------
  961. the function `easygui_fallbackA()' is equivalent to `easyguiA()' apart from
  962. the fact that when EasyGUI fails with the "bigg" exception, it will try
  963. again with topaz-8.  Note that you should never want to rely on topaz, this
  964. function was only added for emergency situations.  If your GUI is too big
  965. on some systems, you should redesign your GUI to fit comfortably instead.
  966. (see other parts of this doc that talk about GUI-size and testing).
  967.  
  968.  
  969. GUI Manipulation
  970. ----------------
  971.  
  972.         closewin(gh)
  973.  
  974. Temporarily closes the GUI window.  Use openwin() to reinstate the GUI.
  975. This function is useful for iconifying a GUI (see the iconify and toolify
  976. PLUGINs).  You can test whether a GUI's window is closed (or otherwise
  977. unmodifiable) by checking if the `wnd' element of the guihandle is NIL.
  978. Note that if your GUI is on the default public screen then it will no
  979. longer be a visitor (i.e., you can then use changescreen() to move it to a
  980. new screen).  (A blocked window is unblocked before it is closed.)
  981.  
  982.         openwin(gh)
  983.  
  984. Reopens a closed GUI window: it will reopen in the same position and size
  985. as it was when it closed.  Note that the window is not guaranteed to open
  986. correctly again (someone may have grabbed your memory, for example).  The
  987. window will always open unblocked.  Once open again, gh.wnd will be non-NIL
  988. (i.e., the address of the window).
  989.  
  990.         changegui(gh,gui)
  991.  
  992. Changes the GUI in a window (fairly) seamlessly.  The old GUI is removed
  993. and the new GUI tries to take its place, resizing if necessary (a NIL `gui'
  994. is just ignored).  The window will be resized if the new GUI's minimum size
  995. is bigger than the current size, or if the new GUI does not allow resizing.
  996. A side-effect of this new, dynamic ability to change GUIs is that the
  997. default window type is to have a size gadget, even the GUI can't be
  998. resized.  You can change this by specifying a different EG_WTYPE, or use
  999. changewindowtype().
  1000.  
  1001.         changemenus(gh,newmenus=NIL)
  1002.  
  1003. Changes the GUI's menus.  If `newmenus' is NIL or not present then the
  1004. current menus are removed and the window is left with no menus.
  1005.  
  1006.         changeinfo(gh,info=-1)
  1007.  
  1008. Changes the GUI's info.  If `info' is -1 or not present then the GUI's
  1009. info is changed to be the guihandle for the window.  (Remember: the info is
  1010. passed to the GUI's action functions.)
  1011.  
  1012.         changetitle(gh,windowtitle=NIL)
  1013.  
  1014. Changes the title of the GUI's window.  (But remember that the title is
  1015. ignored for window type WTYPE_BASIC and WTYPE_NOBORDER.)
  1016.  
  1017.         changescreen(gh,scr=NIL)
  1018.  
  1019. If the GUI window is closed (gh.wnd=NIL) then this will alter the GUI's
  1020. screen (if it's open then this function does nothing).  If `scr' is NIL
  1021. then the default public screen will be used.  If the font was linked to the
  1022. screen then it will be updated, too.
  1023.  
  1024.         changefont(gh,tattr=NIL)
  1025.  
  1026. Again, this works only if the GUI window is closed.  If `tattr' is NIL then
  1027. the font of the screen is used.
  1028.  
  1029.         changewintype(gh,wintype=WTYPE_SIZE)
  1030.  
  1031. Another one that works only if the GUI window is closed.  This sets the
  1032. window border type.  You can use one of WTYPE_NOBORDER, WTYPE_BASIC,
  1033. WTYPE_NOSIZE and WTYPE_SIZE, as described above.
  1034.  
  1035.         movewin(gh,x=-1,y=-1)
  1036.  
  1037. Moves the window of the GUI referenced by gh to the new (top-left)
  1038. coordinate.  If x or y is -1 (the default) then that coordinate is not
  1039. changed.  (Note: the change is delayed until the next INTUITICK.)
  1040.  
  1041.         sizewin(gh,xs=-1,ys=-1)
  1042.  
  1043. Attempts to resize the window of the GUI referenced by gh.  If xs or ys is
  1044. -1 (the default) then that dimension is not changed.  The resizing is not
  1045. guaranteed to be carried out since the size may be smaller than the GUI's
  1046. minimum or the GUI may not be sizable.  (Note: the change is delayed until
  1047. the next INTUITICK.)
  1048.  
  1049. Simple window blocking to prevent the user using a GUI:
  1050.  
  1051.         blockwin(gh)
  1052.  
  1053. This puts up an invisible requester over the window of the GUI referenced
  1054. by gh, and disables window sizing.  If you're running v39+ then the busy
  1055. pointer will be set on this window.  You would use this to block a GUI
  1056. before you put up another one.  Note: the window can still be moved and
  1057. depth arranged.  (This works only if the GUI's window is open.)
  1058.  
  1059.         unblockwin(gh)
  1060.  
  1061. Reinstates the GUI, allowing the user to interact with it again.  The
  1062. blockwin() and unblockwin() calls nest, so you need an equal number of
  1063. unblockwin() calls to blockwin() calls before the window is actually
  1064. unblocked.  Note: a GUI window is implicitly unblocked (forcefully!) when
  1065. it is closed.  In general: try to design your GUIs such that the user can
  1066. use them all simultaneously, this is much friendlier (i.e., make use of the
  1067. multi-window support given by addmultiA()...).
  1068.  
  1069.         checkgui(gh)
  1070.  
  1071. Checks for any GUI messages and processes them, invoking actionfunctions if
  1072. necessary.  If this causes the GUI to want to be closed (e.g., the user has
  1073. pressed the close gadget), then a "QUIT" exception is thrown and the
  1074. exceptioninfo is the value that would have been returned by the easyguiA()
  1075. call (so, as with quitgui(), your exception handlers might like to make
  1076. "QUIT" a special case and just ReThrow() it).
  1077.  
  1078. This function is useful, for example, when you're in an action function
  1079. that's performing a long calculation.  By polling the GUI at convenient
  1080. points using this function you will make the GUI more responsive.  However,
  1081. you are responsible for coping with the possibility that the user may
  1082. cause, for instance, the same action function to be called again.  A simple
  1083. solution is use some kind of semaphore (a global boolean variable, for
  1084. example) to mark whether you are currently in an action function and busy.
  1085. See the led_test.e examples and the old CU Amiga tutorials on Amiga E.
  1086.  
  1087.         checkmulti(mh)
  1088.  
  1089. This is checkgui() for multi-window GUIs.  As mentioned above (in 'Multiple
  1090. Windows') you can use checkgui() to check and act on messages for *all* the
  1091. GUIs in the same group as the one identified by the guihandle, but the
  1092. guihandle must be valid.  This function uses the multihandle so is always
  1093. safe as long as the group exists.
  1094.  
  1095.  
  1096. +---------------------------------------------------------------+
  1097. |       5. PLUGINs                                              |
  1098. +---------------------------------------------------------------+
  1099.  
  1100. PLUGINs allow the programmer to extend EasyGUI with new functionality,
  1101. i.e., to add any kind of rendering/gadgets to the GUI, while cooperating
  1102. automatically with EasyGUI's layout/resizing.  You can use plugins to add
  1103. rendering areas in the midst of EasyGUI gadgetry (e.g., for graphics
  1104. programs), add BOOPSI gadgets to a GUIs etc.  You can supply ready-made
  1105. plugins for other programmers to use.
  1106.  
  1107.         OBJECT plugin
  1108.         /* Public (read-only) parts: */
  1109.           -> Position and size.
  1110.           x:INT,y:INT,xs:INT,ys:INT
  1111.           -> guihandle for the GUI the PLUGIN is on.
  1112.           gh:PTR TO guihandle
  1113.         ENDOBJECT
  1114.  
  1115. Any PLUGIN is an object inherited from the 'plugin' object found in
  1116. easygui.m.  To implement a new plugin all that needs to be done is redefine
  1117. a few methods.  Then, this PLUGIN can be plugged in to any EasyGUI with for
  1118. example:
  1119.  
  1120.         [PLUGIN,{plugaction},NEW mp.myplugin()]
  1121.  
  1122. in your GUI-spec. Whether the action-value is used depends on the PLUGIN,
  1123. as we'll see below.  If it is called it will be passed the PLUGIN object as
  1124. well as the GUI info:
  1125.  
  1126.   PROC pluginaction(info,plugin_object:PTR TO plugin)
  1127.  
  1128. Have a quick look at the plugin example sources, or keep them handy while
  1129. reading the bit below.
  1130.  
  1131. Creating the object
  1132. -------------------
  1133. create your new object as a 'plugin'-subtype.  You may add constructors/
  1134. destructors if you wish.  following methods implement the plugins
  1135. behaviour, and may be redefined:
  1136.  
  1137.         will_resize()
  1138.  
  1139. is called once just before the window is opened.  You should return a
  1140. flag-set telling in which ways your object can resize, making use of the
  1141. constants RESIZEX and RESIZEY, 0 of course meaning your object is fixed in
  1142. size (default method returns RESIZEX OR RESIZEY, i.e., resize in both
  1143. directions).  New to v3.3a is COND_RESIZEX and COND_RESIZEY, which allow
  1144. your PLUGIN to resize in the corresponding direction only if something else
  1145. in its gadget group is unconditionally resizable.  (For example, a BAR is
  1146. conditionally resizable, so that it does not force a group of BUTTONs to be
  1147. resizable.)
  1148.  
  1149.         min_size(ta:PTR TO textattr,fontheight)
  1150.  
  1151. is called once just before the window is opened.  ta is the font used
  1152. in the GUI.  you should return the _minimum_ x and y sizes of your
  1153. PLUGIN as _two_ returnvalues, making use of `fontheight' if you wish.
  1154. Note that EasyGUI may actually grant you a lot more space than just
  1155. the minimum space you ask for, depending on the other gadgets and
  1156. user-resizing.  If your object can have al sorts of sizes, pick a
  1157. relatively small one as minimum.  The default method just returns
  1158. (fontheight,fontheight)
  1159.  
  1160.         render(ta:PTR TO textattr,x,y,xs,ys,win:PTR TO window)
  1161.  
  1162. Here you should render your object to the window.  In the case of a gadget
  1163. this means creating the gadget and attaching it to the window (AddGList(),
  1164. RefreshGList(), make sure you render only your own gadget(s)).  ta is the
  1165. font used in the GUI.  (xs,ys) is always at least the minimum size you
  1166. asked for.  (x,y,xs,ys) is also copied to your object before this method is
  1167. called, for use in other methods).  The default method paints a nice black
  1168. box :-) You shouldn't take too long in this method as it will make window
  1169. redraw look slow.  (It is safe to use existing v3.2e PLUGIN modules, but to
  1170. recompile under v3.3a you will need to add the `ta' argument to your PLUGIN
  1171. render() method.)
  1172.  
  1173.         gtrender(gl,vis,ta:PTR TO textattr,x,y,xs,ys,win:PTR TO window)
  1174.  
  1175. New to v3.3a: a replacement for render() which enables simple addition of
  1176. GadTools gadgets to the standard EasyGUI gadgets.  If you want to use this
  1177. method instead of the normal render() then: 1) the PLUGIN must support it,
  1178. and 2) you must specify TRUE for the `isgt' field of the PLUGIN gadget.
  1179. gtrender() should simply create its gadgets by linking into the current
  1180. list (given by `gl') and using the visual info `vis'.  It should then
  1181. return the new gadget list (i.e., the last GadTools gadget linked in).  And
  1182. then that's it: your GadTools gadgets will be freed automatically, so if
  1183. your PLUGIN is just GadTools gadgets you don't need to override the normal
  1184. (empty) definition clear_render().  If you use gtrender() then you need not
  1185. override render(): this will help indicate a problem if users forget to
  1186. specify `isgt' with your PLUGIN.  See the password PLUGIN example.
  1187.  
  1188.         clear_render(win:PTR TO window)
  1189.  
  1190. mainly useful for gadgets to remove the gadget from the window and free it
  1191. (RemoveGList(), remove only your own gadget(s)!).  Normally render() is
  1192. called when the window opens, and clear_render() when the window closes,
  1193. when the user resizes, however, clear_render() and render() are called one
  1194. after another, in that order, to account for the changed window layout.
  1195. The default method does nothing.
  1196.  
  1197.         message_test(imsg:PTR TO intuimessage,win:PTR TO window)
  1198.  
  1199. is phase-1 of the message handling, splitted in two to not block intuition
  1200. too much.  In message_test() the only thing you should do is return TRUE
  1201. _if_ and _only_if_ the intuimessage is meant for your object, otherwise
  1202. FALSE.  (The only exceptions to this are IDCMP_MOUSEMOVE messages from a
  1203. GACT_FOLLOWMOUSE or WFLG_REPORTMOUSE, which can be ignored safely [i.e.,
  1204. you may return FALSE] as they cannot easily be attributed to an originating
  1205. gadget).  For a mouse-click, test if it was in your area (the current
  1206. dimensions of your object in the GUI are present in the `plugin' object),
  1207. for gadgets, make sure it is really your gadget causing the message (check
  1208. .iaddress).  If you reply TRUE to messages that are potentially meant for
  1209. other objects, you might choke them.  Do not engage in other actions in
  1210. this method, such as rendering; do these things in the message_action()
  1211. method.  The default method returns FALSE.
  1212.  
  1213. The GUI window uses the following IDCMP flags:
  1214.  
  1215.         IDCMP_ACTIVEWINDOW        IDCMP_INACTIVEWINDOW
  1216.         IDCMP_GADGETDOWN          IDCMP_GADGETUP
  1217.         IDCMP_INTUITICKS
  1218.         IDCMP_MOUSEBUTTONS        IDCMP_MOUSEMOVE
  1219.         IDCMP_NEWSIZE
  1220.         IDCMP_RAWKEY              IDCMP_VANILLAKEY
  1221.  
  1222. You may get your PLUGIN objects to generate these messages (via gadgets)
  1223. and then trap them (via message_test()), or you can just snoop on them in
  1224. message_test().
  1225.  
  1226.         message_action(class,qual,code,win:PTR TO window)
  1227.  
  1228. is the second part, and will only be called if you returned TRUE in the
  1229. previous method.  here you may do any action needed (additional rendering
  1230. based on the user action).  class, qual and code are copies of the class,
  1231. qualifier and code part of the intuimessage, so you don't need to remember
  1232. them in message_test().  You should return TRUE if you want the action the
  1233. user of the PLUGIN has written in his GUI-spec to be executed upon
  1234. termination of this method (do this if your object clearly can be "hit",
  1235. such as a gadget.  If you just do some rendering you might want to ignore
  1236. the actionvalue).  The default method returns FALSE.  (As noted above, the
  1237. action function is passed the PLUGIN object as well as the GUI info.)
  1238.  
  1239. Note: do not confuse message_action() with action values: the former is for
  1240. implementing the plugin's behaviour generally, while the latter is for
  1241. specific behaviour in a specific GUI, attached by the user of your plugin
  1242. (which could be you again :-).
  1243.  
  1244.         appmessage(amsg:PTR TO appmessage,win:PTR TO window)
  1245.  
  1246. Like the testing for window IDCMP, but for AppWindow message testing.
  1247. Return TRUE _only_if_ the message is meant for this PLUGIN.  The PLUGINs
  1248. (optional) awproc will then be called (as normal, with the optional data
  1249. field being the `plugin_object').  Note: for compatibility, the
  1250. appmessage() method is called only for PLUGINs that specify a non-NIL
  1251. `awproc' field.  Just be careful to *not* specify a non-NIL `awproc' field
  1252. with old PLUGIN modules.
  1253.  
  1254. If you supply a plugin as module for others, you'll have to state what
  1255. constructor(s) they may use, wether or not they have to supply a sensible
  1256. action-value.  END will almost always have to be called.
  1257.  
  1258.  
  1259. +---------------------------------------------------------------+
  1260. |       6. guide to the examples                                |
  1261. +---------------------------------------------------------------+
  1262.  
  1263. There are numerous examples to show the various features of EasyGUI.
  1264. Here's a small guide to help you find the ones that might be interesting:
  1265.  
  1266.         alldist.e          - The original example.
  1267.         alldist2.e         - The original example, using multi-windows and
  1268.                              blocking.  You can have all the example GUIs
  1269.                              open at once!
  1270.  
  1271.         testaw.e           - AppWindow example.
  1272.         testchange.e       - changegui() example.
  1273.         testchange2.e      - changeXXX() and multi-window example.
  1274.         testkey.e          - Keyboard shortcuts example, with window
  1275.                              blocking and gadget disabling.
  1276.         testmulti.e        - Multi-window example (recursive!).
  1277.         testmulti2.e       - Multi-window and multiforall() example.
  1278.         testqual.e         - Qualifier example.
  1279.  
  1280.         animcontrol_test.e - Tests animcontrol PLUGIN.
  1281.         button_test.e      - Tests flavours of button PLUGIN.
  1282.         calendar_test.e    - Tests calender PLUGIN.
  1283.         colorwheel_test.e  - Tests colorwheel PLUGIN.
  1284.         gradient_test.e    - Tests gradient (slider) PLUGIN.
  1285.         imagebutton_test.e - Tests flavours of imagebutton PLUGIN.
  1286.         led_test.e         - Tests led PLUGIN, with pseudo-async activity.
  1287.         led_test2.e        - Tests led PLUGIN, with multi-windows and
  1288.                              pseudo-async activities.
  1289.         led_test3.e        - Tests led PLUGIN, with multi-windows and
  1290.                              *real* async activities.
  1291.         led_test4.e        - Tests led and ticker PLUGINs, with
  1292.                              multi-windows and pseudo-async activities.
  1293.         password_test.e    - Tests password PLUGIN.
  1294.         tabs_test.e        - Tests tabs PLUGIN.
  1295.         tabs_test2.e       - Tests tabs PLUGIN and changegui() example.
  1296.         tapedeck_test.e    - Tests tapedeck PLUGIN.
  1297.         ticker_test.e      - Tests ticker PLUGIN.
  1298.  
  1299. These can be found in Src/EasyGUI.  The sources for the example PLUGINs are
  1300. in Src/Plugins.
  1301.  
  1302.  
  1303. +---------------------------------------------------------------+
  1304. |       7. bugs/future                                          |
  1305. +---------------------------------------------------------------+
  1306.  
  1307. bugs:
  1308. - method of displaying slider values not bulletproof
  1309. - GadTools sends two messages if your slider value is changed to a
  1310.   negative value, so your action function can get called twice.  
  1311.  
  1312. [the planned render spaces can now be done much better by using PLUGINs]
  1313.  
  1314.  
  1315. ----------------------------------------------------------------
  1316.  
  1317. General advice: try out and modify the examples.  Sometimes something won't
  1318. work, but EasyGUI is flexible enough that at least one way of arranging
  1319. groups etc.  will give you a nice GUI :-).  If you need more power than
  1320. EasyGUI currently gives, you'll have to use MUI/BGUI/WhatEver instead.
  1321.  
  1322. Wouter (and Jason!)
  1323.